# -*- coding: UTF-8 -*-
import os
import types
import hashlib
import datetime
import re
import sys
import shutil
import time
import EXIF

BUFFER_SIZE = 4096 * 4

months = {}
for month in range(1,12+1):
    date = datetime.datetime(1900, month, 1)
    months[month] = date.strftime('%B')

EXTENSION = ('.nef', '.jpg', '.bmp', '.gif', '.tga', '.xcf', '.tiff', '.tif', '.png', '.cr2', '.crw', '.jpeg')


def CheckTargetFilename(filename):
    counter = 1
    path, fname = os.path.split(filename)
    fname, ext = os.path.splitext(fname)
    while os.path.exists(filename):
        filename = os.path.join(path, '%s~%s%s' % (fname, counter, ext))
        counter = counter + 1
    return filename

def getTimeStamp(filename):    
    inputfile = open(filename, 'rb')
    data = None
    try:
        data = EXIF.process_file(inputfile)
    except:
        return datetime.datetime.fromtimestamp(os.stat(filename).st_ctime)

    if not data:
        return datetime.datetime.fromtimestamp(os.stat(filename).st_ctime)

    date = data['EXIF DateTimeDigitized'].values
    datepart, timepart = date.split(' ')
    year, month, day = datepart.split(':')
    hour, minute, second = timepart.split(':')
    year, month, day, hour, minute, second = map(int, [year, month, day, hour, minute, second])
    return datetime.datetime(year, month, day, hour, minute, second)

def image_renamer(filename, just_return_name = False):
    path, fname = os.path.split(filename)
    fname, ext = os.path.splitext(fname)
    if not ext in EXTENSIONS:
        return filename
    
    dt = getTimeStamp(filename)
    timestamp = dt.strftime('%Y%m%d_%H%M%S%f')
    timestamp_count = fname.count(timestamp)

    if timestamp_count == 1:
        return filename

    elif timestamp_count > 1:
        fname = fname.replace(timestamp, '')

    new_filename = CheckTargetFilename(os.path.join(path, '%s_%s%s' % (fname, timestamp, ext)))
    if just_return_name:
        return new_filename
    
    os.rename(filename, new_filename)
    
    return new_filename

def structmaker(filename, basepath, targetpath):
    dt = getTimeStamp(filename)
    
    orgPath, orgFname = os.path.split(filename)
    label = orgPath[len(basepath):]
    if len(label) > 1:
        if label[0] == os.sep:
            label = label[1:]
    if not label:
        label = str(dt.day)
    full_target_path = os.path.join(targetpath, str(dt.year), months[dt.month], label)
    if not os.path.exists(full_target_path):
        os.makedirs(full_target_path)
    new_filename = os.path.join(full_target_path, os.path.basename(filename))
    shutil.move(filename, new_filename)
    return new_filename

class NotImplemented(Exception): pass

def humansize(size):
    """
    Will take a filesize in bytes and return a string with more human-readable info
    """
    if size != 0:
        
        fmt = "%.2f"
        if (size / 1024) == 0 :
            return "%s.2fb" % size
            
        elif (size / 1024) < 1000 and (size/(1024*1024)) == 0 :
            size = float(size / 1024.0)
            return "%.2fk" % size
            
        elif (size / (1024*1024)) < 1000 and (size/(1024*1024*1024)) == 0 :
            size = float(size / ( 1024.0*1024.0))
            return "%.2fMb" % size
        
        elif (size / (1024*1024*1024)) < 1000 and (size/(1024*1024*1024*1024)) == 0 :
            size = float(size / ( 1024.0*1024.0*1024.0))
            return "%.2fGb" % size

        elif (size / (1024*1024*1024*1024)) < 1000 and (size/(1024*1024*1024*1024*1024)) == 0 :
            size = float(size / ( 1024.0*1024.0*1024.0*1024.0))
            return "%.2fTb" % size
            
        else:
            return str(size) + "b"
            
    return '?'

reWord = re.compile(u'[A-Z,a-z]?[a-z]+|[0-9]+')
ignore_words = ['i','for','in','the','a','an','en','ei','ett']

def getWords(text, ignore_words = [], minsize = 2):
    """
    Extracts words from a piece of text.
    It splits words based on spaces, change in char-case inside a text, numbers etc.
    """
    res = {}
    for word in [w.lower() for w in reWord.findall(text)]:
        if w not in ignore_words and len(w) > minsize and not w.isdigit():
            res[word] = None
    return res.keys()

def generate_checksum(filename):
    """
    Generates a hexdigest version of a SHA-512 checksum based on a file.
    """
    m = hashlib.sha512()
    f_in = open(filename)
    data = f_in.read(BUFFER_SIZE)
    while data:
        m.update(data)
        data = f_in.read(BUFFER_SIZE)
    return m.hexdigest()

def parse_filedata(path, complete_filename):
    """
    
    """
    filepath, filename = os.path.split(complete_filename)
    filepath = filepath[len(path):]
    filename, extension = os.path.splitext(filename)
    extension = extension[1:]
    stats = os.stat(complete_filename)    
    filesize = stats.st_size
    created_datetime = datetime.datetime.fromtimestamp(stats.st_ctime)
    modified_datetime = datetime.datetime.fromtimestamp(stats.st_mtime)
    return locals()

def dirwalk(dir, extensions_to_include = None):
    """

    """
    extensions_check = extensions_to_include != None
    for f in os.listdir(dir):
        fullpath = os.path.join(dir,f)
        if os.path.isdir(fullpath) and not os.path.islink(fullpath):
            for x in dirwalk(fullpath, extensions_to_include):
                ext = os.path.splitext(x)[-1][1:].lower()
                if extensions_check == False or ext in extensions_to_include:
                    yield x
        else:
            ext = os.path.splitext(fullpath)[-1][1:].lower()
            if extensions_check == False or ext in extensions_to_include:
                yield fullpath